package p.ithorns.framework.api;

import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.mvc.condition.RequestCondition;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * ApiVersionCondition
 * <p>
 * 重写RequestCondition，自定义url匹配逻辑
 *
 * @author Ht.L
 * @date 2024-03-08 14:46
 * @since 1.0.0
 */
public class ApiVersionCondition implements RequestCondition<ApiVersionCondition> {

    private final static VersionComparator COMPARATOR = new VersionComparator();

    /**
     * 接口路径中的版本号前缀，如: api/v[1-n]/fun
     * // (\d+\.\d+\.\d+)(.+)?  -> 1.0.0-alpha.12.ab-c
     */
    private final static String PATTERN = "/v?((\\d+\\.\\d+\\.\\d+)(.+)?)/?";
    private final static Pattern VERSION_PREFIX = Pattern.compile(PATTERN);

    private final AntPathMatcher pathMatcher = new AntPathMatcher();


    private final String version;

    public ApiVersionCondition(String version) {
        this.version = version;
    }

    @Override
    public ApiVersionCondition combine(ApiVersionCondition other) {
        return version.compareTo(other.version) >= 0
                ? new ApiVersionCondition(version)
                : new ApiVersionCondition(other.version);
    }

    /**
     * 控制只有版本小于等于请求参数中的版本的 ApiVersionCondition 才满足规则
     */
    @Override
    public ApiVersionCondition getMatchingCondition(HttpServletRequest request) {
        String uri = request.getRequestURI();
        Matcher m = VERSION_PREFIX.matcher(uri);
        if (m.find()) {
            String otherVersion = m.group(1);
            if (COMPARATOR.compare(otherVersion, this.version) >= 0) {
                return this;
            }
        }
        return null;
    }

    /**
     * 当出现多个符合匹配条件的ApiVersionCondition，优先匹配版本号较大的
     */
    @Override
    public int compareTo(ApiVersionCondition other, HttpServletRequest request) {
        return compareTo(other);
    }

    public String getApiVersion() {
        return version;
    }

    private int compareTo(ApiVersionCondition other) {
        return COMPARATOR.compare(other.getApiVersion(), this.getApiVersion());
    }

    public static void main(String[] args) {
        AntPathMatcher pathMatcher = new AntPathMatcher();
        Map<String, String> map = pathMatcher
                .extractUriTemplateVariables("/v{ver}", "/1.1.1");

        System.out.println(map);
    }

}